package gamagora.game.map
{
	import flash.utils.Dictionary;
	
	import org.flixel.FlxBasic;
	import org.flixel.FlxG;
	import org.flixel.FlxGroup;
	import org.flixel.FlxSprite;
	
	public class OSLayer
	{
		private var _decalSpeed:Number;
		private var _sprites:Vector.<OSBackground>;
		private var _nbBackgrounds:uint;
		private var _spritesIndices:Vector.<uint>;
		private var _nbSpritesIndices:uint;
		private var _currentSpriteIndex:uint;
		private var _onStart:Boolean;
		private var _onEnd:Boolean;
		private var _scrollPos:Number;
		private var _startScrollPos:Number;
		private var _endScrollPos:Number;
		private var _specials:Vector.<Vector.<uint>>;
		private var _specialsIndices:Vector.<uint>;
		
		public function OSLayer(decalSpeed:Number = 1)
		{
			_decalSpeed = decalSpeed;
			_sprites = new Vector.<OSBackground>();
			_nbBackgrounds = 0;
			
			_spritesIndices = new Vector.<uint>();
			_nbSpritesIndices = 0;
			
			_currentSpriteIndex = 0;
			_scrollPos = 0;
			_startScrollPos = 0;
			_endScrollPos = 0;
			
			_specials = new Vector.<Vector.<uint>>();
			_specialsIndices = new Vector.<uint>();
		}

		public function addBackground(background:OSBackground):uint
		{
			_sprites.push(background);
			_nbBackgrounds++;
			return _nbBackgrounds - 1;
		}
		
		public function addSpecials(specials:Vector.<uint>, startAtMap:uint):void
		{
			_specials.push(specials);
			_specialsIndices.push(startAtMap);
		}
		
		public function generateRandomSequence(maxSprites:uint):void
		{
			var nbIndices:uint = _specialsIndices.length;
			for(var i:uint;i<maxSprites;i++)
			{
				var findSpecial:Boolean = false;
				for(var j:uint=0;j<nbIndices;j++)
				{
					if(_specialsIndices[j] == i)
					{
						findSpecial = true;
						var specials:Vector.<uint> = _specials[j];
						for(var k:uint=0;k<specials.length;k++)
						{
							_spritesIndices.push(specials[k]);
							i++;
						}
						break;
					}
				}
				
				if(!findSpecial)
				{
					_spritesIndices.push(generateRandomBackground());
				}
			}
			_nbSpritesIndices = _spritesIndices.length;
		}
		
		private function generateRandomBackground():uint
		{
			var randomIndex:Number;
			var valid:Boolean = false;
			while(!valid)
			{
				randomIndex = uint(Math.random() * _nbBackgrounds);
				valid = true;
				var nbIndices:uint = _specialsIndices.length;
				for(var i:uint=0;i<nbIndices;i++)
				{
					var specials:Vector.<uint> = _specials[i];
					for(var j:uint=0;j<specials.length;j++)
					{
						if(specials[j] == randomIndex)
						{
							valid = false;
							break;
						}
					}
					
					if(!valid)
					{
						break;
					}
				}
			}
			return randomIndex;
		}
		
		public function draw():void
		{	
			_onStart = OSWorldMap.player.x + OSWorldMap.player.halfWidth <= OSWorldMap.scrollLeftBound;
			_onEnd = OSWorldMap.player.x + OSWorldMap.player.halfWidth >= OSWorldMap.scrollRightBound;
			
			_scrollPos = OSWorldMap.player.x * _decalSpeed;
			_startScrollPos = (OSWorldMap.scrollLeftBound - OSWorldMap.player.halfWidth) * _decalSpeed;
			_endScrollPos = (OSWorldMap.scrollRightBound - OSWorldMap.player.halfWidth) * _decalSpeed;
			
			_currentSpriteIndex = uint((OSWorldMap.player.x + _scrollPos) / OSMap.WIDTH);
			
			if(_currentSpriteIndex >= _nbSpritesIndices)
			{
				_currentSpriteIndex = _nbSpritesIndices - 1;
			}
			
			//Carte précédente
			if(_currentSpriteIndex - 1 >= 0)
			{
				drawBackground(_sprites[_spritesIndices[_currentSpriteIndex - 1]], _currentSpriteIndex * OSMap.WIDTH - OSMap.WIDTH);
			}
			
			//Carte courante
			drawBackground(_sprites[_spritesIndices[_currentSpriteIndex]], _currentSpriteIndex * OSMap.WIDTH);
			
			//Carte suivante
			if(_currentSpriteIndex + 1 < _nbSpritesIndices)
			{
				drawBackground(_sprites[_spritesIndices[_currentSpriteIndex + 1]], _currentSpriteIndex * OSMap.WIDTH + OSMap.WIDTH);
			}
		}
		
		private function drawBackground(background:OSBackground, decal:uint):void
		{
			background.x = decal;
			
			if(_onStart)
			{
				background.x -= _startScrollPos;
			}
			else 
			{
				if(_onEnd)
				{
					background.x -= _endScrollPos;
				}
				else
				{
					background.x -= _scrollPos;
				}
			}
			
			background.update();
			background.draw();
		}
		
		public function destroy():void
		{
			for(var i:uint=0;i<_nbBackgrounds;i++)
			{
				_sprites[i].destroy();
			}
		}
		
		//Getters Setters

		public function get scrollPos():Number
		{
			return _scrollPos;
		}

		public function get onStart():Boolean
		{
			return _onStart;
		}

		public function get onEnd():Boolean
		{
			return _onEnd;
		}
	}
}
